package com.project.controller;



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.project.entity.Orders;
import com.project.mapper.NumberMapper;
import com.project.mapper.OrdersMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.*;
import org.web3j.abi.datatypes.generated.Bytes32;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.utils.Convert;
import cn.hutool.http.HttpUtil;
import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("test")
public class TestController {

    //测试环境
//    private final static Web3j web3j = Web3j.build(new org.web3j.protocol.http.HttpService("http://8.218.20.94:9002/"));
    //正式环境
    private final static Web3j web3j = Web3j.build(new org.web3j.protocol.http.HttpService("http://8.218.20.94:9001/"));
    @Resource
    private NumberMapper numberMapper;
    /**
     * 连接web3 节点
     */
//    private final static Web3j web3j = Web3j.build(new org.web3j.protocol.http.HttpService("https://bsc-dataseed.binance.org/"));
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Resource
    private OrdersMapper ordersMapper;

//    private static BigInteger startBlock= BigInteger.valueOf(21986626);

//    @GetMapping("sendMqTest")
//    public void sendMqTest(){
//        String url = "https://api.bscscan.com/api?module=account&action=txlist&address=0x126189851CF29Ba5A54F9D098fAEd8DA93DFd738&startblock=0&endblock=99999999&page=1&offset=70&sort=desc&apikey=RPD5GJV2FR8PFICJT27NZEFIAYWVHDU9NV";
//        String res = HttpUtil.get(url);
//        JSONObject jsonObjectStatus = (JSONObject) JSONObject.parse(res);
//        System.out.println(jsonObjectStatus);
//        String result = jsonObjectStatus.getString("result");
//        JSONArray resultArray = (JSONArray) JSONObject.parse(result);
//        for (int i = 0; i < 70; i++) {
//            JSONObject array = (JSONObject) resultArray.get(i);
//            String functionName = array.getString("functionName");
//            if (functionName.contains("receiveBNB")) {
//                String wallet = array.getString("from");
//                System.out.println(wallet);
//                String hash = array.getString("hash");
//                String to = array.getString("to");
//                System.out.println(hash);
//                String status=array.getString("txreceipt_status");
//                String input=array.getString("input");
//                BigInteger orderId = new BigInteger(input.substring(10,74), 16);
//                System.out.println(orderId);
//                String value=array.getString("value");
//                BigDecimal bnb = Convert.fromWei(value, Convert.Unit.ETHER);
//                System.out.println(bnb);
//                String parentWallet="0x"+input.substring(98,138);
//                if (status.equals("1")){
////                    Orders orders=ordersMapper.findByHash(hash);
////                    if (orders==null){
//                        MonitorPojo monitorPojo = new MonitorPojo();
//                        monitorPojo.setFrom(to);
//                        monitorPojo.setTimestamp("111");
//                        monitorPojo.setToken(hash);
//                        monitorPojo.setOrderid(String.valueOf(orderId));
//                        monitorPojo.setValue(bnb);
//                        monitorPojo.setUsdtValue(BigDecimal.ZERO);
//                        monitorPojo.setUserWallet(wallet);
//                        monitorPojo.setParentWallet(parentWallet);
//                        String s = JSON.toJSONString(monitorPojo);
//                    System.out.println("fas"+s);
//                    rabbitTemplate.convertAndSend("monitorExchange0", "monitorRouting0", s);
////                    }
//                }
//            }
//        }
//    }
    @GetMapping("contact")
    @ApiOperation("合约监听")
    public void contact() {
//        BigInteger startBlock1=null;
//        BigInteger startBlock= numberMapper.getNumber();
//        try {
//            startBlock1 = web3j.ethBlockNumber().send().getBlockNumber();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        System.out.println(startBlock1);/**/
            BigInteger startBlock=
                BigInteger.valueOf(24919605);
        System.out.println("-----------------------启动的区块高度:"+startBlock);
            System.out.println("------------------------------要监听的合约事件");
            // 要监听的合约事件
            Event event = new Event("setBNB",

                    Arrays.asList(

                            new TypeReference<Address>() {},

                            new TypeReference<Uint>() {},

                            new TypeReference<Uint>(){})
            );
        Event event1 = new Event("getBNB",

                Arrays.asList(

                        new TypeReference<Address>() {},
                        new TypeReference<Address>() {},
                        new TypeReference<Uint>() {},
                        new TypeReference<Uint>() {},
                        new TypeReference<Utf8String>() {},
                        new TypeReference<Utf8String>() {},
                        new TypeReference<Utf8String>() {})
        );

//        Event event2 = new Event("getTokenAndBnb",
//
//                Arrays.asList(
//
//                        new TypeReference<Address>() {},
//
//                        new TypeReference<Uint>() {},
//
//                        new TypeReference<Uint>(){},
//                        new TypeReference<Uint>(){})
//        );

        Event event2 = new Event("getTokenAndBnb",

                Arrays.asList(

                        new TypeReference<Address>() {},
                        new TypeReference<Address>() {},
                        new TypeReference<Address>() {},
                        new TypeReference<Uint>(){},
                        new TypeReference<Uint>(){},
                        new TypeReference<Uint>(){},
                        new TypeReference<Utf8String>() {},
                        new TypeReference<Utf8String>() {},
                        new TypeReference<Utf8String>() {}
                        )
        );

        Event event3 = new Event("setToken",

                Arrays.asList(

                        new TypeReference<Address>() {},

                        new TypeReference<Address>() {},

                        new TypeReference<Uint>(){},
                        new TypeReference<Uint>(){})
        );



            //过滤器

            System.out.println("-------------------------进入过滤器");

            //监听的合约地址,同时监听两个智能合约
            List<String> list=new ArrayList<>();
//            list.add("0x87314951f58f57bfb63ef929a42e78d55c816ce8");
            list.add("0xd7bfA1bfE752912161010687596098fd9e6A38AF");
            //收款合约地址
        list.add("0x126189851CF29Ba5A54F9D098fAEd8DA93DFd738");
            EthFilter filter = new EthFilter(

                    DefaultBlockParameter.valueOf(startBlock),

                    DefaultBlockParameterName.LATEST,

                    list);

            filter.addOptionalTopics(EventEncoder.encode(event),EventEncoder.encode(event1),EventEncoder.encode(event2),
                    EventEncoder.encode(event3));

            System.out.println("-------------------------结束过滤器");
            //注册监听,解析日志中的事件
            AtomicInteger block_TokenSub = new AtomicInteger(startBlock.intValue());
            System.out.println("-------------------------注册监听");
                web3j.ethLogFlowable(filter).subscribe(log -> {
                    try {
                    System.out.println("-------------------------进入监听");

                    block_TokenSub.set(log.getBlockNumber().intValue());

                    System.out.println("-----------------------log"+log);

                    String token = log.getAddress();  //这是Token合约地址


                    String txHash = log.getTransactionHash();

                    List<String> topics = log.getTopics();  // 提取转账记录
                    System.out.println("-----------------转账记录：" + topics);
                    //bnb
                    if (token.equalsIgnoreCase("0x126189851cf29ba5a54f9d098faed8da93dfd738")&&topics.size()==4){
                        String id = topics.get(topics.size() - 2);
                        BigInteger orderId = new BigInteger(id.substring(2), 16);
                        System.out.println("------------------------orderId：" + orderId);

                        String bnbStr = topics.get(topics.size() - 1);
                        BigInteger bnbInt = new BigInteger(bnbStr.substring(2), 16);
                        System.out.println("--------------bnbInt:"+bnbInt);
                       BigDecimal bnb = Convert.fromWei(bnbInt.toString(), Convert.Unit.ETHER);
                        System.out.println("bnb=" + bnb);
                        String userWallet = "0x" + topics.get(1).substring(26);
                        String value1 = log.getData();
                        String parentWallet=value1.substring(26,66);
                        parentWallet="0x"+parentWallet;
                        System.out.println("-------------------parentWallet:"+parentWallet);
                        String fromAddress=token;
                        String timestamp = "1111";

                        MonitorPojo monitorPojo = new MonitorPojo();
                        monitorPojo.setParentWallet(parentWallet);
                        monitorPojo.setFrom(fromAddress);
                        monitorPojo.setTimestamp(timestamp);
                        monitorPojo.setToken(txHash);
                        monitorPojo.setOrderid(String.valueOf(orderId));
                        monitorPojo.setValue(bnb);
                        monitorPojo.setUsdtValue(BigDecimal.ZERO);
                        monitorPojo.setUserWallet(userWallet);
                        String s = JSON.toJSONString(monitorPojo);

                         if (orderId.equals("1")){
                            rabbitTemplate.convertAndSend("monitorExchange1", "monitorRouting1", s);
                        }else if (orderId.equals("2")){
                            rabbitTemplate.convertAndSend("monitorExchange2", "monitorRouting2", s);
                        }else if (orderId.equals("3")){
                            rabbitTemplate.convertAndSend("monitorExchange3", "monitorRouting3", s);
                        }else if (orderId.equals("4")){
                            rabbitTemplate.convertAndSend("monitorExchange4", "monitorRouting4", s);
                        }else if (orderId.equals("5")){
                            rabbitTemplate.convertAndSend("monitorExchange5", "monitorRouting5", s);
                        }else if (orderId.equals("6")){
                            rabbitTemplate.convertAndSend("monitorExchange6", "monitorRouting6", s);
                        }else if (orderId.equals("7")){
                            rabbitTemplate.convertAndSend("monitorExchange7", "monitorRouting7", s);
                        }else if (orderId.equals("8")){
                            rabbitTemplate.convertAndSend("monitorExchange8", "monitorRouting8", s);
                        }else if (orderId.equals("9")){
                            rabbitTemplate.convertAndSend("monitorExchange9", "monitorRouting9", s);
                        }else {
                             rabbitTemplate.convertAndSend("monitorExchange0", "monitorRouting0", s);
                         }
                        System.out.println("-----------------------------------------我发送了个消息" + s);
                    }else {
                        String id = topics.get(topics.size() - 1);
                        BigInteger orderId = new BigInteger(id.substring(2), 16);
                        System.out.println("------------------------orderId：" + orderId);

                        String fromAddress = "0x" + topics.get(1).substring(26);
                        String toAddress = "";
                        if (topics.size() == 4) {
                            toAddress += "0x" + topics.get(2).substring(26);
                        }
//                String toAddress = "0x"+topics.get(2).substring(26);

                        System.out.println("  ---token =" + token + ",  txHash =" + txHash + ",fromAddress=" + fromAddress + ",toAddress=" + toAddress);

                        BigDecimal bnbValue=BigDecimal.ZERO;
                        BigDecimal usdtValue=BigDecimal.ZERO;
                        String userWallet="";
                        String value1 = log.getData();
                        if (orderId.compareTo(new BigInteger("20"))==-1){
                            String value2=value1.substring(2);
                            if (value2.length()>200){
//                                String str="00000000000000000000000000000000000000000000000000005af3107a4000";
//                        System.out.println("-------------------length:"+str.length());
                                String usdt=value2.substring(128,192);
                                System.out.println("----------------------usdt："+usdt);
                                String bnb=value2.substring(192,256);
                                System.out.println("----------------------bnb："+bnb);
                                userWallet=value2.substring(64,128);
                                System.out.println(userWallet);
                                userWallet = userWallet.substring(24);
                                userWallet="0x"+userWallet;
                                BigInteger big = new BigInteger(usdt, 16);
                                System.out.println("---------------big:"+big);
                                usdtValue = Convert.fromWei(big.toString(), Convert.Unit.ETHER);
                                System.out.println("usdtValue=" + usdtValue);

                                BigInteger big2=new BigInteger(bnb,16);
                                bnbValue = Convert.fromWei(big2.toString(), Convert.Unit.ETHER);
                                System.out.println("bnbValue=" + bnbValue);
                            }else {
                                userWallet=toAddress;
                            }
//
                        }else {
                            BigInteger big = new BigInteger(value1.substring(2), 16);

                            usdtValue = Convert.fromWei(big.toString(), Convert.Unit.ETHER);
                            System.out.println("usdtValue=" + usdtValue);
                        }


                        String timestamp = "1111";

                        MonitorPojo monitorPojo = new MonitorPojo();
                        monitorPojo.setFrom(fromAddress);
                        monitorPojo.setTimestamp(timestamp);
                        monitorPojo.setToken(txHash);
                        monitorPojo.setOrderid(String.valueOf(orderId));
                        monitorPojo.setValue(bnbValue);
                        monitorPojo.setUsdtValue(usdtValue);
                        monitorPojo.setUserWallet(userWallet);
                        String s = JSON.toJSONString(monitorPojo);

                        if (orderId.equals("1")){
                            rabbitTemplate.convertAndSend("monitorExchange1", "monitorRouting1", s);
                        }else if (orderId.equals("2")){
                            rabbitTemplate.convertAndSend("monitorExchange2", "monitorRouting2", s);
                        }else if (orderId.equals("3")){
                            rabbitTemplate.convertAndSend("monitorExchange3", "monitorRouting3", s);
                        }else if (orderId.equals("4")){
                            rabbitTemplate.convertAndSend("monitorExchange4", "monitorRouting4", s);
                        }else if (orderId.equals("5")){
                            rabbitTemplate.convertAndSend("monitorExchange5", "monitorRouting5", s);
                        }else if (orderId.equals("6")){
                            rabbitTemplate.convertAndSend("monitorExchange6", "monitorRouting6", s);
                        }else if (orderId.equals("7")){
                            rabbitTemplate.convertAndSend("monitorExchange7", "monitorRouting7", s);
                        }else if (orderId.equals("8")){
                            rabbitTemplate.convertAndSend("monitorExchange8", "monitorRouting8", s);
                        }else if (orderId.equals("9")){
                            rabbitTemplate.convertAndSend("monitorExchange9", "monitorRouting9", s);
                        }else {
                            rabbitTemplate.convertAndSend("monitorExchange0", "monitorRouting0", s);
                        }
                        System.out.println("-----------------------------------------我发送了个消息" + s);
                    }

                    }catch (Exception e){
                        contact();
                        e.printStackTrace();
                    }
                }, error -> {
                    System.out.println(" ### tokenSubscription   error= " + error);
                        contact();
                    error.printStackTrace();

                });

        }

    @GetMapping("tryContact")
    @ApiOperation("合约监听异常")
    public void tryContact() {
        try {
            contact();
        } catch (Exception e) {
            tryContact();
            e.printStackTrace();
        }

    }



    @GetMapping("testMq")
    @ApiOperation("测试MQ发送")
    public void testMq(){
        MonitorPojo monitorPojo=new MonitorPojo();
        monitorPojo.setFrom("0x907ea7a303beeeb7bf51c0525f496e98e56c3547");
        monitorPojo.setTimestamp("123");
        monitorPojo.setToken("0xf037d3f03200c37da798e65ad4e293170ddf747fbd7a3c1d41a3e6a975d49950");
        monitorPojo.setOrderid("0");
        monitorPojo.setValue(new BigDecimal("0.002"));
        monitorPojo.setUsdtValue(new BigDecimal("1.5"));
        String s = JSON.toJSONString(monitorPojo);
        rabbitTemplate.convertAndSend("monitorExchangeNew", "monitorRoutingNew", s);
        System.out.println("-----------------------------------------我发送了个消息"+s);
    }
//
//    @Resource
//    private HttpService httpService;
//    @GetMapping("send")
//    @ApiOperation("给该地址发送消息")
//    public void send(String url){
//
//        MonitorPojo monitorPojo=new MonitorPojo();
//        monitorPojo.setFrom("123");
//        monitorPojo.setTimestamp("1000");
//        monitorPojo.setToken("123");
//        monitorPojo.setTo("123");
//        monitorPojo.setValue(new BigDecimal(10));
//        httpService.sendMsg(url,monitorPojo);
//    }


    @GetMapping("mq")
    @ApiOperation("启动监听")
    public void mq(){

        //监听当前区块以后的交易
        web3j.transactionFlowable().subscribe(tx -> {

            //更新检查过的区块高度

            int  block_EthSub = tx.getBlockNumber().intValue();

            System.out.println("  ---transactionFlowable  block_EthSub = "+block_EthSub);

            String txHash = tx.getHash();
            System.out.println("----------------------------txHssh"+txHash);

            String fromAddress = tx.getFrom();

            System.out.println("--------------------------------fAddress"+fromAddress);
            String toAddress = tx.getTo();
            System.out.println("--------------------------------tAddress"+toAddress);


                BigDecimal value = Convert.fromWei(tx.getValue().toString(), Convert.Unit.ETHER);

                String timestamp = "";

                try {

                    EthBlock ethBlock = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(tx.getBlockNumber()), false).send();

                    timestamp = String.valueOf(ethBlock.getBlock().getTimestamp());

                } catch (IOException e) {

                    System.out.println("Block timestamp get failure,block number is {}" + tx.getBlockNumber());

                    System.out.println("Block timestamp get failure,{}"+  e.getMessage());

                }

                // 监听以太坊上是否有系统生成地址的交易

                MonitorPojo monitorPojo=new MonitorPojo();
                monitorPojo.setFrom(fromAddress);
                monitorPojo.setTimestamp(timestamp);
                monitorPojo.setToken(txHash);
                monitorPojo.setOrderid(toAddress);
                monitorPojo.setValue(value);

//                rabbitTemplate.convertAndSend("directExchange", "TestDirectRouting", monitorPojo);
                System.out.println("-----------------------------------------我发送了个消息"+monitorPojo);



        }, error->{

            System.out.println("   ### transactionFlowable  error= "+ error);
            mq();
            error.printStackTrace();


        });

    }


}
